#include<windows.h>
#include"GameManager.h"
CGameManager::CGameManager(HINSTANCE hInstance, LPWSTR Name, int Mode, int isFullscreen, int FrameRate)
{
	this->d3d=NULL;
	this->d3ddv=NULL;
	this->Mode=Mode;
	this->Name=Name;
	this->IsFullScreen=isFullscreen;
	this->FrameRate=FrameRate;
	this->hInstance=hInstance;
	this->SetScreenDimension(Mode);
}
CGameManager::~CGameManager()
{
	if(d3ddv!=NULL) d3ddv->Release();
	if(d3d!=NULL) d3d->Release();
	if(Keyboard)
	{
		Keyboard->Unacquire();
		Keyboard->Release();
	}
	if(dinput) dinput->Release();
}
bool CGameManager::InitWindow()
{
	WNDCLASSEX wc;
	wc.cbSize=sizeof(WNDCLASSEX);
	wc.style=CS_HREDRAW | CS_VREDRAW;
	wc.hInstance=hInstance;
	wc.lpfnWndProc=(WNDPROC)CGameManager::WinProc;
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hIcon=NULL;
	wc.hCursor=LoadCursor(NULL,IDC_ARROW);
	wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName=NULL;
	wc.lpszClassName=Name;
	wc.hIconSm=NULL;
	
	RegisterClassEx(&wc);
	DWORD style;
	if(IsFullScreen) style= WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP;
	else style=WS_OVERLAPPEDWINDOW;
	hWnd=CreateWindow(Name,Name,style,CW_USEDEFAULT,CW_USEDEFAULT,ScreenWidth,ScreenHeight,NULL,NULL,hInstance,NULL);
	if(!hWnd) return false;
	ShowWindow(hWnd,SW_SHOWNORMAL);
	UpdateWindow(hWnd);
	return true;
}
bool CGameManager::InitDirectX()
{
	if(NULL==(d3d=Direct3DCreate9(D3D_SDK_VERSION)))
	{
		return false ;
	}
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp,sizeof(d3dpp));
	d3dpp.Windowed=IsFullScreen?FALSE:TRUE;
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferCount=1;
	d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;
	d3dpp.BackBufferHeight=ScreenHeight;
	d3dpp.BackBufferWidth=ScreenWidth;
	d3dpp.hDeviceWindow=hWnd;
	if(FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&d3ddv)))
	{
		return false;
	}
	d3ddv->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backbuffer);
	return true;
}
bool CGameManager::InitKeyboard()
{
	HRESULT result=DirectInput8Create(hInstance,DIRECTINPUT_VERSION,IID_IDirectInput8,(VOID**)&dinput,NULL);
	if(result!=DI_OK) return false;
	result=dinput->CreateDevice(GUID_SysKeyboard,&Keyboard,NULL);
	if(result!=DI_OK) return false;
	result=Keyboard->SetDataFormat(&c_dfDIKeyboard);
	result=Keyboard->SetCooperativeLevel(hWnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
	DIPROPDWORD dipdw;
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj        = 0;
    dipdw.diph.dwHow        = DIPH_DEVICE;
    dipdw.dwData            = KEYBOARD_BUFFER_SIZE;
	result=Keyboard->SetProperty(DIPROP_BUFFERSIZE,&dipdw.diph);
	if(result!=DI_OK) return false;
	result=Keyboard->Acquire();
	if(result!=DI_OK) return false;
	return true;
}
void CGameManager::ProcessKeyBoard()
{
	Keyboard->GetDeviceState(sizeof(KeyStates),KeyStates);
	//if(IsKeyDown(DIK_ESCAPE)) PostMessage(hWnd,WM_QUIT,0,0);
	DWORD dwElements= KEYBOARD_BUFFER_SIZE;
	HRESULT result= Keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),KeyEvents,&dwElements,0);
	for(DWORD i=0;i<dwElements;i++)
	{
		int KeyCode=KeyEvents[i].dwOfs;
		int Keystate=KeyEvents[i].dwData;
		if((Keystate & 0x80)>0) OnKeyDown(KeyCode);
		else OnKeyUp(KeyCode);
	}
}
int CGameManager::IsKeyDown(int KeyCode)
{
	return (KeyStates[KeyCode] & 0x80) >0;
}
void CGameManager::OnKeyDown(int KeyCode)
{
}
void CGameManager::OnKeyUp(int KeyCode)
{
}
void CGameManager::ProcessInput(LPDIRECT3DDEVICE9 d3ddv,int time)
{
}

void CGameManager::SetScreenDimension(int Mode)
{
	switch(Mode)
	{
	case RESOLUTION_640_480_24:
		{
			ScreenWidth=640;
			ScreenHeight=480;
			Depth=24;
			backbufferformat=D3DFMT_X8R8G8B8;
		}break;
	case RESOLUTION_800_600_24:
		{
			ScreenWidth=800;
			ScreenHeight=600;
			Depth=24;
			backbufferformat=D3DFMT_X8R8G8B8;
		}break;
	case RESOLUTION_1024_768_24:
		{
			ScreenWidth=1024;
			ScreenHeight=768;
			Depth=24;
			backbufferformat=D3DFMT_X8R8G8B8;
		}break;
	}
}
void CGameManager::Init()
{
	if(!InitWindow()) 
	{
		MessageBox(hWnd,L"Cannot create window!",L"ERROR",MB_OK | MB_ICONERROR);
		return;
	}
	if(!InitDirectX())
	{
		MessageBox(hWnd,L"Cannot create DirectX!",L"ERROR",MB_OK | MB_ICONERROR);
		return;
	}
	if(!InitKeyboard())
	{
		MessageBox(hWnd,L"Cannot create Direct Input!",L"ERROR",MB_OK | MB_ICONERROR);
		return;
	}
	if(!Init_DirectSound(hWnd))
	{
		MessageBox(hWnd,L"Cannot create Direct Sound!",L"ERROR",MB_OK|MB_ICONERROR);
		return ;
	}
}
void CGameManager::LoadResources(LPDIRECT3DDEVICE9 d3ddv)
{
}
void CGameManager::_RenderFrame()
{
	if(d3ddv->BeginScene())
	{
		RenderFrame(d3ddv,timepassed);
		d3ddv->EndScene();
	}
	d3ddv->Present(NULL,NULL,NULL,NULL);
}
void CGameManager::RenderFrame(LPDIRECT3DDEVICE9 d3ddv, int time)
{
	d3ddv->ColorFill(backbuffer,NULL,D3DCOLOR_XRGB(0,0,0));
}
void CGameManager::Run()
{
	MSG msg;
	DWORD framestart=GetTickCount();
	DWORD tickperframe=100/FrameRate;
	ZeroMemory(&msg,sizeof(msg));
	LoadResources(d3ddv);
	while(msg.message!=WM_QUIT)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if(msg.message==275) InitKeyboard();
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		DWORD now= GetTickCount();
		timepassed=now-framestart;
		if(timepassed>=tickperframe)
		{
			framestart=now;
			_RenderFrame();
			ProcessKeyBoard();
		ProcessInput(d3ddv,timepassed);
		}
		
	}
}
LRESULT CALLBACK CGameManager::WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd,message,wParam,lParam);
}
